home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1997 July: Mac OS SDK / Dev.CD Jul 97 SDK1.toast / Development Kits (Disc 1) / QuickDraw GX / Programming Stuff / Sample Code / Graphics Samples / QDGX Debugging (WWDC'94) ƒ / QDGX Debugging (WWDC'94).c < prev    next >
Encoding:
Text File  |  1996-04-15  |  24.2 KB  |  677 lines  |  [TEXT/KAHL]

  1. //
  2. //    These constants are used to turn on the good code (i.e. the non-buggy code)
  3. //
  4. #define kFixCallNewInkFirst                  //     fix the uninitialized gxInk problem
  5. #define kFixMoveScaleRotate                  //     fix the moving, scaling, and rotation into outer space problems
  6. #define kFixTextSize                      //     fix the text too small (i.e. using ints instead of fixed #'s) problem
  7. #define kFixOutliningOfText                  //     fix the outlining of the text to run along the character's geometry
  8. #define kAddPatternToRectangle            //    defining this flag calls the function which adds the pattern to the rectangle
  9. //#define kDrawBitmapPattern
  10. #define kFixPatternRotationFill             //     fix the funky bitmap rotation patterning problem...
  11. #define kDisposeTheCopyOfRectangleShape      //     dispose of the rectangle shape we copied into the picture
  12.   
  13. /**
  14.  --
  15.  --        App:            QDGX Debugging (WWDC'94) 
  16.  --
  17.  -- 
  18.  --        Version:        1.0     4/94:    added all of the calls required to support the "Using QuickDraw™ GX
  19.  --                                In QuickDraw Applications & Debugging Tips" session at the WWDC '94     
  20.  --
  21.  --                        4/96 bob    Updated #includes to support changed GX Library names.
  22.  --                                Updated the note regarding the files needed to run.
  23.  --                                Updated the copyright date.
  24.  --
  25.  --        File:            QDGX Debugging (WWDC'94).c 
  26.  --
  27.  --
  28.  --        Comments:    This code creates a picture shape which contains the following shapes:
  29.  --
  30.  --                     - "G" and "X" as text shapes using the Skia font in 128 points, using a CMYK color,
  31.  --                     and an ADD transfer mode to allow color blending when shapes overlap.
  32.  --
  33.  --                    - two path shapes: one to outline the "G" and the other to outline the "X",
  34.  --                    which are draw as closed frame filled paths.
  35.  --
  36.  --                    - a rectangle shape in a light gray CMYK color
  37.  --
  38.  --                    As we create the shapes mentioned above, they are added to the picture
  39.  --                    shape - gThePage. We will then move this picture shape to the center of
  40.  --                    the window, scale it 3x, and rotate 15 degrees.
  41.  --
  42.  --                    Finally, we add a 15 degree rotated bitmap as a pattern to the rectangle.  This may
  43.  --                    seem straight forward, but the rotation of the bitmap shape causes some interesting
  44.  --                    problems and difficulties. See the comments with the "AddPatternedRectToPicture"
  45.  --                    function for complete details of these issues.
  46.  --
  47.  --                    This is the same code which was used during the"Using QuickDraw™ GX
  48.  --                    In QuickDraw Applications & Debugging Tips" session at the WWDC '94
  49.  --
  50.  --                    During our talk ay the WWDC '94, we demonstrated various bugs and debugging
  51.  --                    techniques. All of the "bugs" are controlled by the #defines below. If you want to see
  52.  --                    a particular bug, comment out the particular #define. There are comments regarding each
  53.  --                    #define below. 
  54.  --
  55.  --                    You can search on "BUG", to find all of the location we introduced a problem and a comment
  56.  --                    describing each fix...
  57.  --
  58.  --                    Also, you will need to install the "GXGraphics(debug)" extension to see and understand 
  59.  --                    all of the bugs. This extension also prevents a "bus error" from a bug within our code
  60.  --                    which GX validation will catch (if you are running the debugging extension).
  61.  --
  62.  --                    To receive the cool graphics effects, you need the following font installed into 
  63.  --                    your system: Skia (this font will be automatically installed, if you use the Installer Script)
  64.  --
  65.  --
  66.  --        Components:    QDGX Debugging (WWDC'94).c
  67.  --                    graphics shell.c
  68.  --                    graphics shell.h
  69.  --
  70.  --                    QDGX Debugging (WWDC'94).c contains all of the QuickDraw GX calls to draw and
  71.  --                    manipulate shapes. All of the interesting QuickDraw GX calls occur within this file.
  72.  --                    This file also contains the following function calls to make the graphics shell.c run
  73.  --                    correctly: DoInitialization, DoDraw, DoClick, DoDispose, DoIdle.
  74.  --
  75.  --                    graphics shell.c contains the event loop and all of the calls to initialize QuickDraw GX.
  76.  --
  77.  --
  78.  --        QuickDraw GX
  79.  --        Libraries
  80.  --        Used:        This application uses the following QuickDraw GX library code files:
  81.  --                    "ColorLibrary.c", "FontLibrary.c", "GraphicsDebugLibrary.c", "QDLibrary.c", 
  82.  --                    "TransferModeLibrary.c", and "TransformLibrary.c".
  83.  --                     
  84.  --        
  85.  --        Notes:            1) Print this file in landscape for the best results
  86.  --        
  87.  --                       2) If you are using THINK C v6.x, I have added THINK markers to navigate the code.
  88.  --        
  89.  --                    3) All of the functions are ordered in the order (top of this file to the bottom) they are called.
  90.  --
  91.  --
  92.  --        Authors:        Pete "Luke" Alexander          and      Herb Derby
  93.  --                    Developer Technical Support        QuickDraw GX Engineer
  94.  --                    AppleLink: DEVSUPPORT
  95.  --
  96.  --        
  97.  --        ©1992 - 1996  Apple Computer, Inc. 
  98.  --        All rights reserved.
  99.  --
  100. **/
  101.  
  102. #include <events.h>
  103. #include <windows.h>
  104.  
  105. #include "GraphicsLibraries.h"
  106. #include "QDLibrary.h"
  107. #include "FontLibrary.h"
  108. #include <GXEnvironment.h>
  109. #include <GXErrors.h>
  110. #include "graphics shell.h"
  111.  
  112.  
  113. //
  114. //    Prototypes used _only_ within this file
  115. //
  116. void AddARectToPicture ( void  );
  117. void ColorTheRectInPicture ( void  );
  118. void ScaleAndRotateRectInPicture ( void  );
  119. void AddTextToPicture ( void  );
  120. void InitColorMatrix( Fixed xferModeMatrix[5][4] );
  121. void AddTransferModeToShape ( gxShape shapeWantingXferMode  );
  122. void AddPatternedRectToPicture ( void  );
  123.  
  124.  
  125. //
  126. //      Set up the title and size of the window 
  127. //
  128. Str255         gWindowTitle = "\p QuickDraw™ GX Debugging - WWDC '94 ";
  129. Rect             gWindowQDRect  = {50, 10, 475, 575};
  130.  
  131.  
  132. //
  133. //    gGraphicsHeapSize sets the size of the graphics heap created by calling the NewGraphicsClient routine
  134. //    in main () within graphics shell.c.  You can determine the amount of graphics heap required by using GraphicsBug.
  135. //    With  gGraphicsHeapSize set to 65k, I had 8 free blocks left in the QuickDraw GX heap. When I tried to 
  136. //    use a 65k, I received the disposed_dead_caches notice. This tells us the GX required additional memory to 
  137. //    complete an operation, therefore it needed to toss away outdated caches to complete the task. This is not necesarily
  138. //     bad, but an additional 8k solved this problem and prevented the disposing....
  139. //
  140. long            gGraphicsHeapSize = 72;
  141.  
  142. gxShape         gThePage;                    // the picture shape containing all of shapes created and drawn
  143.  
  144.  
  145.  
  146. /*------ DoInitialization ---------------------------------------------------------------------------------*/
  147. //
  148. //    This function creates the picture we want to add 5 shapes to and makes the appropriate function calls to 
  149. //    create them.
  150. //
  151. void DoInitialization(theWindow)
  152. WindowPtr theWindow;
  153. {
  154.     //
  155.     //    Create an empty picture shape to hold all of our shapes. After creating the picture shape, we can add
  156.     //    shapes at will....
  157.     //
  158.     gThePage = GXNewShape (gxPictureType); 
  159.     
  160.     AddTextToPicture ( );
  161.     AddARectToPicture ( );
  162.     ColorTheRectInPicture ( );
  163.     ScaleAndRotateRectInPicture ( );
  164.     
  165.     #ifdef kAddPatternToRectangle
  166.         AddPatternedRectToPicture ( );
  167.     #endif
  168. }
  169.  
  170.  
  171. /*------ InitColorMatrix --------------------------------------------------------------------------------*/
  172. //
  173. //    This function takes the matrix passed in and sets it to the identity. It was taken from the "transferMode libray.c".
  174. //
  175. void InitColorMatrix(Fixed xferModeMatrix[5][4])
  176. {
  177.     register Fixed         *x;
  178.     register int         loop;
  179.  
  180.     x = &xferModeMatrix[0][0];
  181.     
  182.     //
  183.     //    Initialize the matrix passed in to be filled full of 0's
  184.     //
  185.     for(loop = 19; loop >=0; loop--)
  186.         *x++ = 0;
  187.     
  188.     //
  189.     // Add the identity matrix, for cleanliness 
  190.     //    
  191.     xferModeMatrix[0][0] = xferModeMatrix[1][1] = xferModeMatrix[2][2] = xferModeMatrix[3][3] = fixed1;
  192. }
  193.  
  194.  
  195. /*------ AddTransferModeToShape -----------------------------------------------------------------------*/
  196. //
  197. //    This function creates an Add transfer mode.
  198. //
  199. void AddTransferModeToShape ( shapeWantingXferMode )
  200. gxShape shapeWantingXferMode;
  201. {
  202.     gxTransferMode    newAddTransferMode;
  203.     int                loop;
  204.  
  205.     newAddTransferMode.space             = gxCMYKSpace;
  206.     newAddTransferMode.flags             = 0;
  207.     newAddTransferMode.set                 = nil;
  208.     newAddTransferMode.profile             = nil;
  209.     
  210.     //
  211.     //    Set each component of the transfer mode..
  212.     //
  213.     for ( loop = 0; loop < 4; loop++ )
  214.     {
  215.         newAddTransferMode.component[ loop ].mode = gxAddMode;
  216.         newAddTransferMode.component[ loop ].flags = 0;
  217.  
  218.         newAddTransferMode.component[ loop ].operand = 0x8000;
  219.         
  220.         newAddTransferMode.component[ loop ].sourceMinimum = 0;
  221.         newAddTransferMode.component[ loop ].sourceMaximum = 65535;
  222.  
  223.         newAddTransferMode.component[ loop ].deviceMinimum = 0;
  224.         newAddTransferMode.component[ loop ].deviceMaximum = 65535;
  225.  
  226.         newAddTransferMode.component[ loop ].clampMinimum = 0;
  227.         newAddTransferMode.component[ loop ].clampMaximum = 65535;
  228.         
  229.     }
  230.  
  231.     //
  232.     //    Initialize each matrix used within the transfer mode to contain the identity matrix
  233.     //
  234.     InitColorMatrix( newAddTransferMode.sourceMatrix );
  235.     InitColorMatrix( newAddTransferMode.deviceMatrix );
  236.     InitColorMatrix( newAddTransferMode.resultMatrix );
  237.  
  238.     GXSetShapeTransfer( shapeWantingXferMode, &newAddTransferMode );
  239. }
  240.  
  241.  
  242. /*------ AddTextToPicture ------------------------------------------------------------------------------*/
  243. //
  244. //    This function creates the "G" and "X"  text shapes and the paths which outline each. The "G" and "X" text shapes
  245. //    are colored in a CMYK color using the Add transfer mode and the Skia Regular font (with it's bold axis set to it's 
  246. //    maximum). The Skia font is a new TrueType GX variation font. The outlines of the "G" and "X" text shapes are closed
  247. //    frame filled paths colored in back with the copy transfer mode. 
  248. //
  249. void AddTextToPicture ( )
  250. {
  251.     gxStyle             textStyle = GXNewStyle();
  252.     gxFont            theSkiaFont;
  253.     Fixed            maxVariationValue;
  254.     gxFontVariation        fontVariation;
  255.     long                result;
  256.     gxColor            textColor, blackTextColor;
  257.     gxShape            textShape, tempTextShape;
  258.     gxPoint            textLocation = {  ff(0), ff(0) };
  259.     
  260.     //
  261.     //    Create a new style to contain: the font, font size, the 'wght' axis of the font set to the
  262.     //    maximum value allowed for this font, set the pen size, and the location of the pen when 
  263.     //    drawing.
  264.     //    
  265.     GXSetStylePen( textStyle, ff(2) );
  266.      
  267.          //
  268.          //    Here's a BUG, all numbers which are used as a parameter to a GX function must be in 
  269.          //    in fixed point. Otherwise, you will receive very, very, very, small numbers when ints are passed in.
  270.          //    The "ff" macro calls the IntToFixed (...) function.
  271.          //
  272.          #ifdef kFixTextSize
  273.         GXSetStyleTextSize( textStyle, ff(128) );
  274.     #else
  275.            GXSetStyleTextSize( textStyle, 128 );
  276.     #endif
  277.     
  278.     //
  279.     //    Create a GX font using the Skia regular font...
  280.     //
  281.     theSkiaFont = FindPNameFont ( gxFullFontName, "\pSkia Regular" );
  282.     GXSetStyleFont( textStyle, theSkiaFont );
  283.     
  284.     //
  285.     //     Here's a BUG (or unwanted behavior), since we are scaling and rotating our picture, we want to
  286.     //    turn "off" all of the metrics and hinting used by TrueType GX while it draws. If you do not turn them
  287.     //    off for the text, the outline for each character will not line up (i.e.  scale linearly) correctly.
  288.     //
  289.          #ifdef kFixOutliningOfText
  290.             GXSetStyleTextAttributes( textStyle, gxNoMetricsGridText | gxNoContourGridText );
  291.     #endif
  292.     
  293.     //
  294.     //    If the "result" is good, we proceed to set the "wght" axis to the maximum value. If the 
  295.     //    "result" is bad, this probably means that the "Skia" font has not been installed. In this
  296.     //    case we cannot set the "wght" axis, so we do not and we alert the user. We will be able 
  297.     //    to continue at this point, but we will not have the fat juicy letters.
  298.     //
  299.     result = GXFindFontVariation( theSkiaFont, 'wght', nil, nil, &maxVariationValue, nil );
  300.  
  301.     if (result) {
  302.         fontVariation.name     = 'wght';
  303.         fontVariation.value    = maxVariationValue;
  304.     
  305.          GXSetStyleFontVariations( textStyle, 1, &fontVariation );
  306.          
  307.     } else  DebugStr ("\p NO 'wght' axis....");
  308.  
  309.     //
  310.     //    Set up as CMYK color space which will used to color all of our text shapes. The "G" will
  311.     //    be colored in magenta. Each text shape will use a different CMYK color. We change the setting
  312.     //    for our "textColor" when we create each new shape.
  313.     //
  314.     textColor.space                 = gxCMYKSpace;
  315.     textColor.element.cmyk.cyan         = 0x0000;
  316.     textColor.element.cmyk.magenta     = 0xffff;
  317.     textColor.element.cmyk.yellow     = 0x0000;
  318.     textColor.element.cmyk.black         = 0x0000;
  319.     textColor.profile                 = nil;
  320.     
  321.     //
  322.     //    Create the "G", and set it's: style, transfer mode, color, and shape fill. Once created, add it to 
  323.     //    the end of our picture....
  324.     //
  325.     textShape = GXNewText (1, (unsigned char*) "G", &textLocation );
  326.      GXSetShapeStyle( textShape, textStyle );
  327.      GXSetShapeColor( textShape, &textColor );
  328.     AddTransferModeToShape ( textShape );        // This function is defined above to add the transfer mode to the "G"
  329.  
  330.      GXSetPictureParts( gThePage, 0, 0, 1, &textShape, nil, nil, nil );
  331.  
  332.     //
  333.     //    We create a unique copy of our "G" and convert it into a path shape to outline the "G". This outline will 
  334.     //    be in black using a copy transfer mode. We set the transfer mode to copy to prevent the printing system from
  335.     //    performing unneeded work...
  336.     //
  337.     tempTextShape = GXCopyToShape ( nil, textShape );
  338.     GXSetShapeType( tempTextShape, gxPathType ); 
  339.     GXSetShapeFill( tempTextShape,  gxClosedFrameFill );
  340.  
  341.     blackTextColor.space                 = gxCMYKSpace;
  342.     blackTextColor.element.cmyk.cyan         = 0x0000;
  343.     blackTextColor.element.cmyk.magenta     = 0x0000;
  344.     blackTextColor.element.cmyk.yellow     = 0x0000;
  345.     blackTextColor.element.cmyk.black         = 0xffff;
  346.     blackTextColor.profile                 = nil;
  347.     
  348.     SetShapeCommonTransfer (tempTextShape, gxCopyMode );
  349.     
  350.      GXSetShapeColor( tempTextShape, &blackTextColor );
  351.     GXSetPictureParts( gThePage, 0, 0, 1, &tempTextShape, nil, nil, nil  );
  352.  
  353.     GXDisposeShape( tempTextShape );  
  354.     GXDisposeShape( textShape );  
  355.     
  356.     //
  357.     //    Set the CYMK color to be cyan.
  358.     //
  359.     textColor.element.cmyk.magenta     = 0x0000;
  360.     textColor.element.cmyk.cyan         = 0xffff;
  361.     
  362.     //
  363.     //    Create the "X" text shape, set it's transfer mode to gxAddMode by calling our AddTransferModeToShape function, 
  364.     //    and set it's starting location, set the color, attach the style, and set the shape fill.
  365.     //
  366.     textLocation.x += ff( 60 );
  367.      textShape = GXNewText ( 1, (unsigned char*) "X", &textLocation );
  368.       GXSetShapeStyle( textShape, textStyle );
  369.     GXSetShapeColor( textShape, &textColor );
  370.     AddTransferModeToShape ( textShape );
  371.  
  372.     GXSetPictureParts( gThePage, 0, 0, 1, &textShape, nil, nil, nil );
  373.  
  374.     tempTextShape = GXCopyToShape ( nil, textShape );
  375.     
  376.     //
  377.     //    Create the outline of the "X". We convert our "X" text shape to a path, color it black, and set the fill to be 
  378.     //    closed frame.
  379.     //
  380.     GXSetShapeType( tempTextShape, gxPathType ); 
  381.     GXSetShapeFill( tempTextShape,  gxClosedFrameFill ) ;
  382.      GXSetShapeColor( tempTextShape, &blackTextColor );
  383.     SetShapeCommonTransfer (tempTextShape, gxCopyMode );
  384.  
  385.     GXSetPictureParts( gThePage, 0, 0, 1, &tempTextShape, nil, nil, nil );
  386.  
  387.     //
  388.     //    Dispose of the shapes and styles which are no longer needed. All of this information is now contained 
  389.     //    within our picture shape - gThePage.
  390.     //
  391.     GXDisposeShape( tempTextShape );  
  392.     GXDisposeShape( textShape );  
  393.     GXDisposeStyle( textStyle );  
  394. }
  395.  
  396.  
  397. /*------ AddARectToPicture -----------------------------------------------------------------------------*/
  398. //
  399. //    This function adds the background rectangle to our picture shape. We add this shape to the
  400. //    beginning of the picture.
  401. //
  402. void AddARectToPicture ( )
  403. {
  404.     gxShape            tempRectShape;
  405.     gxRectangle        pictureBounds;
  406.  
  407.     //
  408.     //    Get the bounds of the picture shape. At this point, it contains 4 shapes (2 text & 2 paths). The
  409.     //    bounding box will encompass the area required to draw all of the shapes created at this point. 
  410.     //    We will then inset the shape to provide better visual effects and color mixing.
  411.     //
  412.     GXGetShapeBounds( gThePage, 0, &pictureBounds );
  413.     
  414.     tempRectShape = GXNewRectangle( &pictureBounds );
  415.      GXInsetShape( tempRectShape, ff(10) );
  416.  
  417.      GXSetPictureParts( gThePage, 1, 0, 1, &tempRectShape, nil, nil, nil );
  418.  
  419.     GXDisposeShape( tempRectShape );  
  420. }
  421.  
  422.  
  423. /*------ ColorTheRectInPicture --------------------------------------------------------------------------*/
  424. //
  425. //    This function changes the color of your rectangle to be a light gray CMYK colored rectangle.
  426. //
  427. void ColorTheRectInPicture ( )
  428. {
  429.     gxColor        cmykColor;
  430.     //
  431.     //    Here's the BUG, you MUST call GXNew___ before using any GX object. If you have the "GXGraphics(debug)"
  432.     //    extension installed and validation turned on, you will receive a validation error, if you try to use an
  433.     //     uninitialized GX object. Otherwise, you will bus error...
  434.     //
  435.     #ifdef kFixCallNewInkFirst
  436.         gxInk         grayCMYKInk = GXNewInk ();
  437.     #else
  438.         gxInk         grayCMYKInk;
  439.     #endif
  440.     gxShape        rectShapeFromPicture;
  441.         
  442.     //
  443.     //    Create the light gray CMYK color 
  444.     //
  445.     cmykColor.space                 = gxCMYKSpace;
  446.     cmykColor.element.cmyk.cyan         = 0x0000;
  447.     cmykColor.element.cmyk.magenta     = 0x0000;
  448.     cmykColor.element.cmyk.yellow     = 0x0000;
  449.     cmykColor.element.cmyk.black         = 0x7000;
  450.     cmykColor.profile                 = nil;            // by passing nil, tells GX to not color match a shape
  451.                                                 // using this ink (color)...
  452.  
  453.     GXSetInkColor( grayCMYKInk, &cmykColor );
  454.  
  455.     GXGetPictureParts( gThePage, 1, 1, &rectShapeFromPicture, nil, nil, nil );
  456.     
  457.     GXSetShapeInk( rectShapeFromPicture, grayCMYKInk );
  458.  
  459.     GXDisposeInk ( grayCMYKInk );
  460. }
  461.  
  462.  
  463. /*------ ScaleAndRotateRectInPicture --------------------------------------------------------------------*/
  464. //
  465. //    This function moves our picture shape into the center of the window, scales it by 3, and rotates it (-15) degrees.
  466. //
  467. //    These macros are used within the function to determine the width and height of our picture and window.
  468. //
  469. #define width( r ) ((r).right - (r).left)
  470. #define height( r ) ((r).bottom - (r).top)
  471.  
  472. void ScaleAndRotateRectInPicture ( )
  473. {
  474.     gxRectangle     pictureBounds;
  475.     gxRectangle     windowBounds;
  476.     gxPoint         theCenter;
  477.     gxPoint         theTopLeft;
  478.     
  479.     GXGetShapeBounds( gWindowBoundsShape, 0, &windowBounds );
  480.     GXGetShapeBounds( gThePage, 0, &pictureBounds );
  481.     
  482.     //
  483.     //    Determine the center of the window
  484.     //
  485.     theCenter.x = width( windowBounds ) >> 1;
  486.     theCenter.y = height( windowBounds ) >> 1; 
  487.  
  488.     //
  489.     //    Determine the top left corner were we should place our picture shape to be in the center of the window
  490.     //
  491.     theTopLeft.x = theCenter.x - ( width( pictureBounds) >> 1 );
  492.     theTopLeft.y = theCenter.y + ( height( pictureBounds) >> 1 );
  493.     
  494.     //
  495.     //    Here's the BUG, you MUST move the shape before we scale and rotate it to prevent it from 
  496.     //    being transformed into outer space....
  497.     //
  498.     #ifdef kFixMoveScaleRotate
  499.         GXMoveShape( gThePage, theTopLeft.x, theTopLeft.y );
  500.         GXScaleShape( gThePage, ff(3), ff(3), theCenter.x, theCenter.y);
  501.         GXRotateShape( gThePage, -ff(15), theCenter.x, theCenter.y );
  502.     #else
  503.         GXScaleShape( gThePage, ff(3), ff(3), theCenter.x, theCenter.y);
  504.         GXRotateShape( gThePage, -ff(15), theCenter.x, theCenter.y );
  505.         GXMoveShape( gThePage, theTopLeft.x, theTopLeft.y );
  506.     #endif
  507. }
  508.  
  509.  
  510.  
  511. /*------ AddPatternedRectToPicture ---------------------------------------------------------------------*/
  512. //
  513. //    This function adds a bitmap shape as a pattern to our rectangle. The bitmap shape is rotated 45 degrees. This
  514. //    rotation causes an interesting problem which is described below.
  515. //
  516. void AddPatternedRectToPicture ( )
  517. {
  518.     gxShape            dogcowBitmapShape,
  519.                     tempRectShape , 
  520.                     rectShapeFromPicture,
  521.                     newBitmapClipShape;
  522.     gxRectangle         patternBounds;
  523.     gxPatternRecord    thePattern;
  524.     gxPolar            toRotate;
  525.     gxTransform        transformFromPicture, invertedTransform;
  526.     gxMapping            theMapping;
  527.     
  528.     //
  529.     //    Get the pixmap from the a resource file. If we fail in our attempt to create dogcowBitmapShape, 
  530.     //    GXValidateShape will let us know via the debugger. 
  531.     //
  532.     dogcowBitmapShape = GetPixMapShape( 128 );
  533.     GXValidateShape ( dogcowBitmapShape );
  534.  
  535.     GXGetShapeBounds( dogcowBitmapShape, 0L, &patternBounds);
  536.  
  537.     //
  538.     //    Turn off all attributes used by our bitmap shape. By default, the gxMapTransformShape shape
  539.     //    attribute is set for bitmap shapes. We turn this off because we want the rotation to occur on 
  540.     //    the geometry of our shape (i.e. the bits). This is required because the transform of the pattern's
  541.     //    shape is ignored once it has been added as a pattern shape. You can force the transform of the
  542.     //    pattern shape to be added to the shape by calling GXMapShape. This solves the previously described
  543.     //    problem, but the transform's clip is ignored when a shape is used as a pattern. We fix this problem below...
  544.     //
  545.     GXSetShapeAttributes( dogcowBitmapShape, gxNoAttributes );
  546.     
  547.     //
  548.     //    Here's part of the BUG,  we want to fill the rectangle with a bitmap shape rotated 45 degrees. So, we
  549.     //    rotate it. Ths kinda of works, but the clip shape is lost by the bitmap shape once it is added to the
  550.     //    pattern record. This is bad, because the bitmap shape is only partially drawn correctly. The bottom
  551.     //    half of the shape looks like corregated steel....
  552.     //
  553.     #if !defined(kFixPatternRotationFill) 
  554.          GXRotateShape( dogcowBitmapShape, ff(45), 0, 0 );
  555.     #endif
  556.  
  557.     #ifdef kDrawBitmapPattern
  558.          GXDrawShape ( dogcowBitmapShape );
  559.     #endif
  560.     
  561.     //
  562.     //    Set up the pattern record to allow our bitmap pattern shape be placed side by side.
  563.     //
  564.     thePattern.u.x             = 0;
  565.     thePattern.u.y             = (patternBounds.bottom - patternBounds.top) ;
  566.  
  567.     #ifdef kFixPatternRotationFill
  568.         thePattern.v.x             = (patternBounds.right - patternBounds.left) ;
  569.         thePattern.v.y             = 0;
  570.         thePattern.u.x             = 0;
  571.     #else
  572.         PointToPolar( &thePattern.u, &toRotate );
  573.         toRotate.angle += ff(45);
  574.         PolarToPoint( &toRotate, &thePattern.u );
  575.         
  576.         thePattern.v.x = (patternBounds.right - patternBounds.left);
  577.         thePattern.v.y = 0;
  578.     
  579.         PointToPolar( &thePattern.v, &toRotate );
  580.         toRotate.angle += ff(45);
  581.         PolarToPoint( &toRotate, &thePattern.v );
  582.     #endif
  583.  
  584.     thePattern.attributes = gxNoAttributes;
  585.     thePattern.pattern      = dogcowBitmapShape;
  586.  
  587.     GXGetPictureParts( gThePage, 1, 1, &rectShapeFromPicture, nil, nil, nil );
  588.     tempRectShape = GXCopyToShape ( nil, rectShapeFromPicture );
  589.  
  590.     GXSetShapePattern( tempRectShape, &thePattern );
  591.     
  592.     #ifdef kFixPatternRotationFill
  593.         transformFromPicture = GXGetShapeTransform ( gThePage );
  594.         invertedTransform = GXCopyToTransform( nil, transformFromPicture );
  595.         GXGetTransformMapping( invertedTransform, &theMapping );
  596.         
  597.         GXSetShapeAttributes( tempRectShape, gxNoAttributes );
  598.         GXSetShapeMapping( tempRectShape, &theMapping );
  599.         RotateMapping( &theMapping, -ff(45), 0, 0 );
  600.         GXMapShape( tempRectShape, &theMapping );
  601.  
  602.         InvertMapping( &theMapping, &theMapping );
  603.         GXSetTransformMapping( invertedTransform,  &theMapping );
  604.         
  605.         GXSetPictureParts( gThePage, 1, 1, 1, &tempRectShape, nil, nil, &invertedTransform );
  606.  
  607.         GXDisposeTransform( invertedTransform );  
  608.     #else
  609.         GXSetPictureParts( gThePage, 1, 1, 1, &tempRectShape, nil, nil, nil );
  610.     #endif
  611.  
  612.     #if !defined kDrawBitmapPattern
  613.         GXDisposeShape( dogcowBitmapShape );  
  614.     #endif
  615.  
  616.     #ifdef kDisposeTheCopyOfRectangleShape
  617.         GXDisposeShape( tempRectShape );  
  618.     #endif
  619. }
  620.  
  621.  
  622. /*------ DoDraw ---------------------------------------------------------------------------------------*/
  623. //
  624. //    This function performs all of the drawing by calling GXDrawShape on our picture - gThePage.
  625. //
  626. void DoDraw( theWindow )
  627. WindowPtr theWindow;
  628. {
  629.     GXDrawShape ( gThePage );
  630. }
  631.  
  632.  
  633. /*------ DoDispose -------------------------------------------------------------------------------------*/
  634. //
  635. //    This function tosses all of the shapes and the window we have created.
  636. //
  637. void DoDispose( theWindow )
  638. WindowPtr theWindow;
  639. {
  640.     //  
  641.     //    You should always dispose of your QuickDraw GX objects before tossing your window. Why? It's generally good 
  642.     //    form and this approach guarantees that everything is disposed. If you had not disposed of everything, the
  643.     //    call to DisposeWindow should dispose of the objects. If you are running the debugging version of the 
  644.     //    "GXGraphics(debug)" extension with warnings enabled, you will receive a warning that you had not disposed of
  645.     //    everything when you app quits. 
  646.     //
  647.     //    Notices are enabled within the "graphics shell.c" automatically, if you have installed the debug
  648.     //    extension. We determine if the debug extension is installed by making the appropriate Gestalt call while the
  649.     //    graphics shell is starting up; see the "graphics shell.c" file for details.
  650.     //
  651.     GXDisposeShape( gThePage );  
  652.      GXDisposeShape( gWindowBoundsShape );              // This shape is created within "graphics shell.c" at start up...
  653.         DisposeWindow( theWindow );
  654. }
  655.     
  656.  
  657.  
  658. /*------ DoClick ---------------------------------------------------------------------------------------*/
  659. //
  660. //    This function handles click by the user...
  661. //
  662. void DoClick( orgMouseLoc, theWindow )
  663. gxPoint        orgMouseLoc;
  664. WindowPtr     theWindow;
  665. {
  666. }
  667.  
  668.  
  669. /*------ DoIdle ----------------------------------------------------------------------------------------*/
  670. //
  671. //    This function is called within the event loop when the "graphics shell" receives a null event...
  672. //
  673. void DoIdle(theWindow)
  674. WindowPtr theWindow;
  675. {
  676. }
  677.